package com.cencat.common.utils;

import com.cencat.common.constant.CommonConstants;
import com.cencat.common.exception.BusinessException;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 文件工具类
 */
public class FileUtils {
    
    private FileUtils() {
        // 私有构造器
    }
    
    /**
     * 检查文件扩展名是否允许
     * @param filename 文件名
     * @return 是否允许
     */
    public static boolean isAllowedFileType(String filename) {
        if (StringUtils.isBlank(filename)) {
            return false;
        }
        
        String extension = getFileExtension(filename);
        if (StringUtils.isBlank(extension)) {
            return false;
        }
        
        for (String allowed : CommonConstants.ALLOWED_FILE_TYPES) {
            if (allowed.equalsIgnoreCase(extension)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 获取文件扩展名
     * @param filename 文件名
     * @return 扩展名
     */
    public static String getFileExtension(String filename) {
        if (StringUtils.isBlank(filename)) {
            return "";
        }
        
        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex == -1 || lastDotIndex == filename.length() - 1) {
            return "";
        }
        
        return filename.substring(lastDotIndex + 1).toLowerCase();
    }
    
    /**
     * 生成唯一文件名
     * @param originalFilename 原始文件名
     * @return 唯一文件名
     */
    public static String generateUniqueFilename(String originalFilename) {
        if (StringUtils.isBlank(originalFilename)) {
            return UUID.randomUUID().toString();
        }
        
        String extension = getFileExtension(originalFilename);
        String baseName = UUID.randomUUID().toString();
        
        if (StringUtils.isNotBlank(extension)) {
            return baseName + "." + extension;
        }
        
        return baseName;
    }
    
    /**
     * 检查文件大小是否超过限制
     * @param fileSize 文件大小（字节）
     * @return 是否超过限制
     */
    public static boolean isFileSizeExceeded(long fileSize) {
        return fileSize > CommonConstants.MAX_FILE_SIZE;
    }
    
    /**
     * 格式化文件大小
     * @param size 文件大小（字节）
     * @return 格式化后的字符串
     */
    public static String formatFileSize(long size) {
        if (size < 1024) {
            return size + " B";
        } else if (size < 1024 * 1024) {
            return String.format("%.2f KB", size / 1024.0);
        } else if (size < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", size / (1024.0 * 1024.0));
        } else {
            return String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0));
        }
    }
    
    /**
     * 创建目录（如果不存在）
     * @param dirPath 目录路径
     * @return 是否创建成功
     */
    public static boolean createDirectoryIfNotExists(String dirPath) {
        if (StringUtils.isBlank(dirPath)) {
            return false;
        }
        
        try {
            Path path = Paths.get(dirPath);
            if (!Files.exists(path)) {
                Files.createDirectories(path);
            }
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    
    /**
     * 删除文件
     * @param filePath 文件路径
     * @return 是否删除成功
     */
    public static boolean deleteFile(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return false;
        }
        
        try {
            Path path = Paths.get(filePath);
            return Files.deleteIfExists(path);
        } catch (IOException e) {
            return false;
        }
    }
    
    /**
     * 复制文件
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     * @return 是否复制成功
     */
    public static boolean copyFile(String sourcePath, String targetPath) {
        if (StringUtils.isBlank(sourcePath) || StringUtils.isBlank(targetPath)) {
            return false;
        }
        
        try {
            Path source = Paths.get(sourcePath);
            Path target = Paths.get(targetPath);
            
            // 确保目标目录存在
            createDirectoryIfNotExists(target.getParent().toString());
            
            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    
    /**
     * 移动文件
     * @param sourcePath 源文件路径
     * @param targetPath 目标文件路径
     * @return 是否移动成功
     */
    public static boolean moveFile(String sourcePath, String targetPath) {
        if (StringUtils.isBlank(sourcePath) || StringUtils.isBlank(targetPath)) {
            return false;
        }
        
        try {
            Path source = Paths.get(sourcePath);
            Path target = Paths.get(targetPath);
            
            // 确保目标目录存在
            createDirectoryIfNotExists(target.getParent().toString());
            
            Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    
    /**
     * 读取文件内容为字符串
     * @param filePath 文件路径
     * @return 文件内容
     */
    public static String readFileToString(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return null;
        }
        
        try {
            return new String(Files.readAllBytes(Paths.get(filePath)), CommonConstants.CHARSET_UTF8);
        } catch (IOException e) {
            throw new BusinessException("读取文件失败: " + filePath, e);
        }
    }
    
    /**
     * 写入字符串到文件
     * @param filePath 文件路径
     * @param content 内容
     * @return 是否写入成功
     */
    public static boolean writeStringToFile(String filePath, String content) {
        if (StringUtils.isBlank(filePath) || content == null) {
            return false;
        }
        
        try {
            // 确保目录存在
            createDirectoryIfNotExists(Paths.get(filePath).getParent().toString());
            
            Files.write(Paths.get(filePath), content.getBytes(CommonConstants.CHARSET_UTF8));
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    
    /**
     * 读取文件内容为字节数组
     * @param filePath 文件路径
     * @return 字节数组
     */
    public static byte[] readFileToBytes(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return null;
        }
        
        try {
            return Files.readAllBytes(Paths.get(filePath));
        } catch (IOException e) {
            throw new BusinessException("读取文件失败: " + filePath, e);
        }
    }
    
    /**
     * 写入字节数组到文件
     * @param filePath 文件路径
     * @param bytes 字节数组
     * @return 是否写入成功
     */
    public static boolean writeBytesToFile(String filePath, byte[] bytes) {
        if (StringUtils.isBlank(filePath) || bytes == null) {
            return false;
        }
        
        try {
            // 确保目录存在
            createDirectoryIfNotExists(Paths.get(filePath).getParent().toString());
            
            Files.write(Paths.get(filePath), bytes);
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    
    /**
     * 获取文件MIME类型
     * @param filePath 文件路径
     * @return MIME类型
     */
    public static String getMimeType(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return null;
        }
        
        try {
            Path path = Paths.get(filePath);
            return Files.probeContentType(path);
        } catch (IOException e) {
            return null;
        }
    }
    
    /**
     * 获取文件大小
     * @param filePath 文件路径
     * @return 文件大小（字节）
     */
    public static long getFileSize(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return 0;
        }
        
        try {
            Path path = Paths.get(filePath);
            return Files.size(path);
        } catch (IOException e) {
            return 0;
        }
    }
    
    /**
     * 检查文件是否存在
     * @param filePath 文件路径
     * @return 是否存在
     */
    public static boolean exists(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return false;
        }
        
        return Files.exists(Paths.get(filePath));
    }
    
    /**
     * 列出目录下的所有文件
     * @param dirPath 目录路径
     * @return 文件列表
     */
    public static List<String> listFiles(String dirPath) {
        List<String> files = new ArrayList<>();
        
        if (StringUtils.isBlank(dirPath)) {
            return files;
        }
        
        try {
            Files.list(Paths.get(dirPath))
                .filter(Files::isRegularFile)
                .forEach(path -> files.add(path.getFileName().toString()));
        } catch (IOException e) {
            // 忽略异常，返回空列表
        }
        
        return files;
    }
    
    /**
     * 列出目录下的所有子目录
     * @param dirPath 目录路径
     * @return 子目录列表
     */
    public static List<String> listDirectories(String dirPath) {
        List<String> directories = new ArrayList<>();
        
        if (StringUtils.isBlank(dirPath)) {
            return directories;
        }
        
        try {
            Files.list(Paths.get(dirPath))
                .filter(Files::isDirectory)
                .forEach(path -> directories.add(path.getFileName().toString()));
        } catch (IOException e) {
            // 忽略异常，返回空列表
        }
        
        return directories;
    }
    
    /**
     * 获取文件最后修改时间
     * @param filePath 文件路径
     * @return 最后修改时间
     */
    public static long getLastModifiedTime(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return 0;
        }
        
        try {
            Path path = Paths.get(filePath);
            return Files.getLastModifiedTime(path).toMillis();
        } catch (IOException e) {
            return 0;
        }
    }
    
    /**
     * 验证文件是否为图片
     * @param filename 文件名
     * @return 是否为图片
     */
    public static boolean isImageFile(String filename) {
        if (StringUtils.isBlank(filename)) {
            return false;
        }
        
        String extension = getFileExtension(filename);
        return "jpg".equalsIgnoreCase(extension) ||
               "jpeg".equalsIgnoreCase(extension) ||
               "png".equalsIgnoreCase(extension) ||
               "gif".equalsIgnoreCase(extension) ||
               "bmp".equalsIgnoreCase(extension) ||
               "webp".equalsIgnoreCase(extension);
    }
    
    /**
     * 验证文件是否为文档
     * @param filename 文件名
     * @return 是否为文档
     */
    public static boolean isDocumentFile(String filename) {
        if (StringUtils.isBlank(filename)) {
            return false;
        }
        
        String extension = getFileExtension(filename);
        return "pdf".equalsIgnoreCase(extension) ||
               "doc".equalsIgnoreCase(extension) ||
               "docx".equalsIgnoreCase(extension) ||
               "xls".equalsIgnoreCase(extension) ||
               "xlsx".equalsIgnoreCase(extension) ||
               "ppt".equalsIgnoreCase(extension) ||
               "pptx".equalsIgnoreCase(extension) ||
               "txt".equalsIgnoreCase(extension);
    }
    
    /**
     * 验证文件是否为压缩文件
     * @param filename 文件名
     * @return 是否为压缩文件
     */
    public static boolean isArchiveFile(String filename) {
        if (StringUtils.isBlank(filename)) {
            return false;
        }
        
        String extension = getFileExtension(filename);
        return "zip".equalsIgnoreCase(extension) ||
               "rar".equalsIgnoreCase(extension) ||
               "7z".equalsIgnoreCase(extension) ||
               "tar".equalsIgnoreCase(extension) ||
               "gz".equalsIgnoreCase(extension);
    }
}